/**
 * Historico de alteração
 *
 * Data         Autor   Descrição
 * 24/10/2010   Jerry   Criação do cabeçalho.
 *
 */
package Conexao;
import Dados.Fila;
import Dados.Pacote;
import java.io.IOException;
import java.io.PrintStream;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;
import Dados.Enderecos;
import java.io.DataInputStream;
import java.util.HashMap;

/**
 *
 * @author Bruno
 */
public class Cliente extends Thread {

    private Socket socket = null;
    private Pacote pack;
    private PrintStream dado_saida = null;
    private DataInputStream dado_entrada = null;
    private Fila fila_tabela;
    private Fila fila_instrumentos;
    private Fila fila_bd;
    private boolean status_tabela = false;
    private boolean status_instrumentos = false;
    private boolean status_bd = false;
    private int[] cabecalho = new int[8];
    private float[] ponderacoes;
    private Enderecos lista_enderecos;
    private HashMap<String, Float> velocidades_anteriores;
    private HashMap<String, Float> posicoes;

//TODO colocar estacoes associadas com ips

    public Cliente(Socket socket, Fila fila_tabela, Fila fila_instrumentos, Fila fila_bd, boolean status_tabela, boolean status_instrumentos, boolean status_bd, Enderecos lista_enderecos) {
        this.socket = socket;
        this.fila_tabela = fila_tabela;
        this.fila_instrumentos = fila_instrumentos;
        this.fila_bd = fila_bd;
        this.status_tabela = status_tabela;
        this.status_instrumentos = status_instrumentos;
        this.status_bd = status_bd;
        this.lista_enderecos = lista_enderecos;
        ponderacoes = new float[4];
        ponderacoes[0] = 108;
        ponderacoes[1] = 85;
        ponderacoes[2] = (float) 2.5;
        ponderacoes[3] = 250;
        try {
            velocidades_anteriores = new HashMap<String, Float>();
            posicoes = new HashMap<String, Float>();
            inicializaHashs();
            dado_saida = new PrintStream(socket.getOutputStream());
            dado_entrada = new DataInputStream(socket.getInputStream());

        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

   /* private Pacote recebeDados() {
        char pack_temp[] = new char[51];
        try {
            dado_entrada.read(pack_temp, 0, 51);
            pack = new Pacote(pack_temp);
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        return pack;
    }*/

    private void inicializaHashs() {
        for(int i = 0; i < lista_enderecos.getQuantidadeEnderecos(); i++) {
            velocidades_anteriores.put(lista_enderecos.getEndereco(i), 0F);
            posicoes.put(lista_enderecos.getEndereco(i), 0F);
        }

    }

    private Pacote recebeDados2() {
        int dado;
        int aux;
        int aux2 = 0;
        char[] dado_hexa = new char[2];
        char[] pacoteXbee = new char[56];
        int indice_pacote = 0;
        int i = 0;
        int tamanho_atual_pacote = 0;
        int trem = -1;
        float[] canais = new float[4];
        String endereco_pacote_atual = "";
        float velocidade_anterior;
        float posicao = 0;
        float media_passageiros;
        Pacote pacote = null;
        try {
        while(tamanho_atual_pacote != 28) {
            
            dado = dado_entrada.readUnsignedByte();
            dado_hexa = toHexa(dado);
            

            if(detectaCabecalho(dado_hexa)) {
                 pacoteXbee[indice_pacote] = dado_hexa[0];
                 pacoteXbee[indice_pacote + 1] = dado_hexa[1];
                 tamanho_atual_pacote = i;
                 i = 0;
                 indice_pacote = 0;
            }
            if(i > 0) {
                 pacoteXbee[indice_pacote] = dado_hexa[0];
                 pacoteXbee[indice_pacote + 1] = dado_hexa[1];
                 indice_pacote += 2;
            }
            i++;

        }
       canais =  ObterValoresCanais(pacoteXbee, ponderacoes);
       endereco_pacote_atual = obterEndereco(pacoteXbee);
       velocidade_anterior = velocidades_anteriores.get(endereco_pacote_atual);
       posicao = posicoes.get(endereco_pacote_atual);
       posicao += (0.125/2*(canais[0] + velocidade_anterior))/1000;
       posicoes.put(endereco_pacote_atual, posicao);
       media_passageiros = (float) ((canais[1] - 36.65) * 52);
       velocidades_anteriores.put(endereco_pacote_atual, canais[0]);
       pacote = new Pacote("WEK", endereco_pacote_atual, canais[0], canais[1], canais[2], canais[3], posicao, (int) media_passageiros);


        } catch (IOException ex) {
            Logger.getLogger(Cliente.class.getName()).log(Level.SEVERE, null, ex);
        }
        return pacote;
    }

    public void enviaDados(String msg) {
        dado_saida.println(msg);
    }

    public Socket getSocket() {
        return socket;
    }

    @Override
    public void run() {
                while(true) {

                    pack = recebeDados2();

                    if(status_tabela) {
                        fila_tabela.insert(pack);
                    }
                    if(status_instrumentos) {
                        fila_instrumentos.insert(pack);
                    }
                    if(status_bd) {
                        fila_bd.insert(pack);
                    }
                }
    }

    public boolean getStatusTabela() {
        return status_tabela;
    }

    public void setStatusTabela(boolean status_tabela) {
        this.status_tabela = status_tabela;
    }

    public boolean getStatusInstrumentos() {
        return status_instrumentos;
    }

    public void setStatusInstrumentos(boolean status_instrumentos) {
        this.status_instrumentos = status_instrumentos;
    }

    public boolean getStatusBD() {
        return status_bd;
    }

    public void setStatusBD(boolean status_bd) {
        this.status_bd = status_bd;
    }

    public char[] toHexa(int a) {
        char[] dado_hexa = new char[2];

        dado_hexa[0] = toChar(a/16);
        dado_hexa[1] = toChar(a%16);

       return dado_hexa;
    }

    private char toChar(int a) {
      switch (a){
        case(0): return '0';
        case(1): return '1';
        case(2): return '2';
        case(3): return '3';
        case(4): return '4';
        case(5): return '5';
        case(6): return '6';
        case(7): return '7';
        case(8): return '8';
        case(9): return '9';
        case(10): return 'A';
        case(11): return 'B';
        case(12): return 'C';
        case(13): return 'D';
        case(14): return 'E';
        case(15): return 'F';
      }
      return 'X';
    }

 int toDecimal(char valor) {

   switch (valor){

    case('0'): return 0;
    case('1'): return 1;
    case('2'): return 2;
    case('3'): return 3;
    case('4'): return 4;
    case('5'): return 5;
    case('6'): return 6;
    case('7'): return 7;
    case('8'): return 8;
    case('9'): return 9;
    case('A'): return 10;
    case('B'): return 11;
    case('C'): return 12;
    case('D'): return 13;
    case('E'): return 14;
    case('F'): return 15;

  }
 return 20;

}

    boolean detectaCabecalho(char[] dado) {

        cabecalho[0] = cabecalho[2];
        cabecalho[1] = cabecalho[3];
        cabecalho[2] = cabecalho[4];
        cabecalho[3] = cabecalho[5];
        cabecalho[4] = cabecalho[6];
        cabecalho[5] = cabecalho[7];

        cabecalho[6] = dado[0];
        cabecalho[7] = dado[1];


        if(cabecalho[0]=='7' && cabecalho[1]=='E' && cabecalho[2]=='0' && cabecalho[3]=='0' && cabecalho[4]=='1' && cabecalho[5] == '8' && cabecalho[6]=='9' && cabecalho[7] == '2') {
             return true;
        }
        return false;
    }

    public int getTrem(byte[] pacote, String[] enderecos) {

        for(int i = 0; i < enderecos.length; i++) {
            if(pacote.toString().substring(0, 15).equals(enderecos[i])) {
                return i;
            }
        }
        return - 1;
    }

    public float[] ObterValoresCanais(char[] pacote, float[] ponderacoes){
    
    int i = 0;
    int j = 0;
    int k = 0;
    int exp = 3;
    float[] canais = new float[4];


    for(i=30;i<46;i+=4){
           for(j=0;j<4;j++){
               canais[k] = (float) (canais[k] + (toDecimal(pacote[i + j]) * Math.pow(16, exp)));
               exp--;
           }

       canais[k] = (float) (canais[k] * ponderacoes[k] * 0.001171875) ;
       exp = 3;
       k++;
    }
      return canais;
}
    
    public String obterEndereco(char[] pacote) {
        
        String endereco = "";
        
        for(int i = 0; i < 16; i++) {
            endereco += pacote[i];
        }
        return endereco;
    }





}
